/**
 * utils.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "utils.h"

static char base64_table[64] =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/**
 * config parsing helper functions
 */

int
cfgstr2bool(const char *s, int *bo)
{
	char *true[] = { "true", "yes", "enable", NULL };
	char *false[] = { "false", "no", "disable", NULL };
	int i;

	for (i = 0; true[i]; ++i)
		if (!strcasecmp(s, true[i])) {
			*bo = 1;
			return 0;
		}

	for (i = 0; false[i]; ++i)
		if (!strcasecmp(s, false[i])) {
			*bo = 0;
			return 0;
		}

	fprintf(stderr, "logical value was expected (got %s)\n", s);
	return 1;
}

int
cfgstr2int(const char *s, int *i)
{
	if (sscanf(s, "%d", i) != 1) {
		fprintf(stderr, "integer value was expected (got %s)\n", s);
		return 1;
	}
	return 0;
}

int
cfgstr2double(const char *s, double *d)
{
	if (sscanf(s, "%lf", d) != 1) {
		fprintf(stderr, "real value was expected (got %s)\n", s);
		return 1;
	}
	return 0;
}

/**
 * data mining helper functions
 */

int
collect_data_from_file(
	const char *fname, const char *sep, int num,
	const char *idlist[], char *valuelist[]
)
{
	char buf[256];
	FILE *fp = fopen(fname, "rt");
	int nread = 0;
	size_t seplen = strlen(sep);

	if (!fp) return nread;
	while (fgets(buf, sizeof(buf), fp) == buf) {
		char *s, *t;
		int i;


		t = strstr(buf, sep);
		if (!t) continue;
		*t = '\0';
		s = t - 1;
		t += seplen;

		while (s >= buf && *s < 33) *s-- = '\0';
		for (s = buf; *s && *s < 33; ++s);

		for (i = 0; i < num; ++i)
			if (!strcmp(s, idlist[i]) && !valuelist[i])
				break;

		if (i >= num) continue;

		while (*t && *t < 33) ++t;
		for (s = t + strlen(t) - 1; s >= t && *s < 33; *s-- = '\0');
		valuelist[i] = strdup(t);
		++nread;
		if (nread >= num) break;
	}
	fclose(fp);
	return nread;
}

/* handles partial send() */
ssize_t
sendall(int s, const void *buf, size_t len, int flags)
{
	const char *p = (const char *)buf;
	int i;

	for (i = 10; len && i; --i) {
		ssize_t n = send(s, p, len, flags);
		if (n < 0) return n;
		if (!n) continue;
		len -= n;
		p += n;
	}
	return p - (char *)buf;
}

char *
base64_encode(const char *s, size_t len)
{
	size_t size = ((len + 2) / 3) * 4 + 1; /* +1: EOS */
	size_t k = len % 3;
	char *p, *buf = (char *)malloc(size);

	if (!buf) return NULL;
	p = buf;
	while (len) {
		int i = ((unsigned)(*s++)) << 16;
		if (len > 1) i |= ((unsigned)(*s++)) << 8;
		if (len > 2) i |= ((unsigned)(*s++));
		len = (len > 3) ? len - 3 : 0;
		*p++ = base64_table[(i >> 18) & 0x3f];
		*p++ = base64_table[(i >> 12) & 0x3f];
		*p++ = base64_table[(i >>  6) & 0x3f];
		*p++ = base64_table[ i        & 0x3f];
	}
	*p = '\0';
	if (k) {
		k = 3 - k;
		while (k) p[-k--] = '=';
	}
	return buf;
}
